package com.uziot.boot.config;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ObjectUtils;

/**
 * flow的配置实体类
 * 这个类中的属性为什么不用基本类型，而用包装类型呢
 * 是因为这个类是springboot和spring的最终参数获取器，考虑到spring的场景，有些参数不是必须配置。基本类型就会出现默认值的情况。
 * 所以为了要有null值出现，这里采用包装类型
 *
 * @author shidt
 */
public class FlowConfig {

    /**
     * 是否启动flow自动装配
     */
    private Boolean enable;

    /**
     * 流程定义资源地址
     */
    private String ruleSource;

    /**
     * zk配置的node定义
     */
    private String zkNode;

    /**
     * slot的数量
     */
    private Integer slotSize;

    /**
     * 并行线程执行器class路径
     */
    private String threadExecutorClass;

    /**
     * 异步线程最大等待秒数
     */
    private Integer whenMaxWaitSeconds;

    /**
     * 是否打印监控log
     */
    private Boolean enableLog;

    /**
     * 监控存储信息最大队列数量
     */
    private Integer queueLimit;

    /**
     * 延迟多少秒打印
     */
    private Long delay;

    /**
     * 每隔多少秒打印
     */
    private Long period;

    /**
     * 异步线程池最大线程数
     */
    private Integer whenMaxWorkers;

    /**
     * 异步线程池最大队列数量
     */
    private Integer whenQueueLimit;

    /**
     * 是否在启动时解析规则文件
     * 这个参数主要给编码式注册元数据的场景用的，结合FlowBus.addNode一起用
     */
    private Boolean parseOnStart;
    /**
     * 这个属性为true，则支持多种不同的类型的配置
     * 要注意，不能将主流程和子流程分配在不同类型配置文件中
     */
    private Boolean supportMultipleType;

    /**
     * 重试次数
     */
    private Integer retryCount;
    /**
     * 节点执行器的类全名
     */
    private String nodeExecutorClass;

    /**
     * 是否打印liteflow banner
     */
    private Boolean printBanner;

    public Boolean getEnable() {
        if (ObjectUtils.isEmpty(enable)) {
            return true;
        } else {
            return enable;
        }
    }

    public void setEnable(Boolean enable) {
        this.enable = enable;
    }

    public String getRuleSource() {
        return ruleSource;
    }

    public void setRuleSource(String ruleSource) {
        this.ruleSource = ruleSource;
    }

    public Integer getSlotSize() {
        if (ObjectUtils.isEmpty(slotSize)) {
            return 1024;
        } else {
            return slotSize;
        }
    }

    public void setSlotSize(Integer slotSize) {
        this.slotSize = slotSize;
    }

    public Integer getWhenMaxWaitSeconds() {
        if (ObjectUtils.isEmpty(whenMaxWaitSeconds)) {
            return 15;
        } else {
            return whenMaxWaitSeconds;
        }
    }

    public void setWhenMaxWaitSeconds(Integer whenMaxWaitSeconds) {
        this.whenMaxWaitSeconds = whenMaxWaitSeconds;
    }

    public Integer getQueueLimit() {
        if (ObjectUtils.isEmpty(queueLimit)) {
            return 200;
        } else {
            return queueLimit;
        }
    }

    public void setQueueLimit(Integer queueLimit) {
        this.queueLimit = queueLimit;
    }

    public Long getDelay() {
        if (ObjectUtils.isEmpty(delay)) {
            return 300000L;
        } else {
            return delay;
        }
    }

    public void setDelay(Long delay) {
        this.delay = delay;
    }

    public Long getPeriod() {
        if (ObjectUtils.isEmpty(period)) {
            return 300000L;
        } else {
            return period;
        }
    }

    public void setPeriod(Long period) {
        this.period = period;
    }

    public Boolean getEnableLog() {
        if (ObjectUtils.isEmpty(enableLog)) {
            return false;
        } else {
            return enableLog;
        }
    }

    public void setEnableLog(Boolean enableLog) {
        this.enableLog = enableLog;
    }

    public Integer getWhenMaxWorkers() {
        if (ObjectUtils.isEmpty(whenMaxWorkers)) {
            return 16;
        } else {
            return whenMaxWorkers;
        }
    }

    public void setWhenMaxWorkers(Integer whenMaxWorkers) {
        this.whenMaxWorkers = whenMaxWorkers;
    }

    public Integer getWhenQueueLimit() {
        if (ObjectUtils.isEmpty(whenQueueLimit)) {
            return 512;
        } else {
            return whenQueueLimit;
        }
    }

    public void setWhenQueueLimit(Integer whenQueueLimit) {
        this.whenQueueLimit = whenQueueLimit;
    }

    public Boolean isParseOnStart() {
        if (ObjectUtils.isEmpty(parseOnStart)) {
            return true;
        } else {
            return parseOnStart;
        }
    }

    public void setParseOnStart(Boolean parseOnStart) {
        this.parseOnStart = parseOnStart;
    }

    public Boolean isSupportMultipleType() {
        if (ObjectUtils.isEmpty(supportMultipleType)) {
            return false;
        } else {
            return supportMultipleType;
        }
    }

    public void setSupportMultipleType(Boolean supportMultipleType) {
        this.supportMultipleType = supportMultipleType;
    }

    public int getRetryCount() {
        if (ObjectUtils.isEmpty(retryCount) || retryCount < 0) {
            return 0;
        } else {
            return retryCount;
        }
    }

    public void setRetryCount(int retryCount) {
        this.retryCount = retryCount;
    }

    public String getZkNode() {
        if (StringUtils.isBlank(zkNode)) {
            return "/lite-flow/flow";
        } else {
            return zkNode;
        }
    }

    public void setZkNode(String zkNode) {
        this.zkNode = zkNode;
    }

    public Boolean getPrintBanner() {
        if (ObjectUtils.isEmpty(printBanner)) {
            return Boolean.TRUE;
        } else {
            return printBanner;
        }
    }

    public void setPrintBanner(Boolean printBanner) {
        this.printBanner = printBanner;
    }

    public String getThreadExecutorClass() {
        if (StringUtils.isBlank(threadExecutorClass)) {
            return "com.uziot.flow.thread.LiteFlowDefaultExecutorBuilder";
        } else {
            return threadExecutorClass;
        }
    }

    public void setThreadExecutorClass(String threadExecutorClass) {
        this.threadExecutorClass = threadExecutorClass;
    }

    public String getNodeExecutorClass() {
        if (StringUtils.isBlank(nodeExecutorClass)) {
            return "com.uziot.flow.entity.executor.DefaultNodeExecutor";
        } else {
            return nodeExecutorClass;
        }
    }

    public void setNodeExecutorClass(String nodeExecutorClass) {
        this.nodeExecutorClass = nodeExecutorClass;
    }
}
